#!/usr/bin/env ruby

=begin
Copyright (c) 2011, Radosław „radmen” Mejer
Copyright (c) 2009, Karol „Zal” Zalewski
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 * Neither the name of the Radosław „radmen” Mejer and Karol „Zal” Zalewski nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=end

=begin

INSTRUKCJA OBSŁUGI

1. Wygeneruj, pobierz i rozpakuj z Jogger.pl plik z eksportem (Panel administracyjny -> Opcje -> Eksport),
2. Zainstaluj WordPressa (baza danych musi być czysta - należy usunąć "powitalny" komentarz),
3. Zmień w niniejszym skrypcie dane dot. bazy MySQL zawierającej dane WordPressa oraz ścieżkę dostępu do pliku XML z eksportem (5 zmiennych po komentarzu "config"),
4. Uruchom skrypt. W przypadku większych blogów czas pracy może wynosić nawet 30 minut.
4.1. Warto nie przeglądać strony podczas importowania danych. Wordpress tworzy szkice przeglądanych postów (jeśli jest się zalogowanym) przez następuje konflikt podczas dodawania rekordów do bazy

=end

require "rexml/document"
require "rubygems"
require "mysql"
require "iconv"

include REXML

# config

$server = ""
$user = ""
$pass = ""
$database = ""
$file_path = ""
$table_prefix = "wp_"

def cleanUp(dbh)
	# truncate categories (and alsto tags and other term-related things - BEWARE!)
	dbh.query("TRUNCATE " + $table_prefix + "term_relationships")
	dbh.query("TRUNCATE " + $table_prefix + "term_taxonomy")
	dbh.query("TRUNCATE " + $table_prefix + "terms")

	# truncate posts a comments table
	dbh.query("TRUNCATE " + $table_prefix + "posts");
	dbh.query("TRUNCATE " + $table_prefix + "comments");
end

def insertCategory(dbh, name)
	slug = Iconv.iconv('ascii//translit', 'utf-8', name)[0].strip.gsub(/\W+/, '-').downcase

	query = "INSERT INTO " + $table_prefix + "terms " +
		"SET" +
		"	name = '" + name + "'," +
		"	slug = '" + slug + "'"
		
	dbh.query(query)
	id = dbh.insert_id()
	
	dbh.query("INSERT INTO " + $table_prefix + "term_taxonomy SET term_id = " + id.to_s + ", taxonomy = 'category'")
	id = dbh.insert_id()
end

def assignCategory2Post(dbh, post_id, term_taxonomy_id)
	dbh.query("INSERT INTO " + $table_prefix + "term_relationships SET object_id = " + post_id.to_s + ", term_taxonomy_id = " + term_taxonomy_id.to_s)
end

begin
	# connect to the MySQL server
	dbh = Mysql.real_connect($server, $user, $pass, $database)
	
	# thanks to this all inserted data will be in UTF8
	dbh.query("SET NAMES utf8");
	
	cleanUp(dbh)
	
	# cache for inserted categories
	categories_cache = {}
	
	# get the XML data
	file = File.new($file_path)

	# extract event information
	doc = Document.new(file)
	root = doc.root

	postId = Integer(1)

	root.each_element("entry") {

		|entry|
		
		date, jid, level_id, comment_mode, subject,
		body, tags, permalink, trackback, category = nil

		entry.each_element("date") {|x| date = x.text}

		entry.each_element("jid") {|x| jid = x.text}

		entry.each_element("level_id") {|x| level_id = x.text}
		entry.each_element("comment_mode") {|x| comment_mode = x.text}
		entry.each_element("subject") {|x| subject = x.text}

		entry.each_element("body") {|x| body = x.text}
		
		entry.each_element("tags") {|x| tags = x.text}
		entry.each_element("permalink") {|x| permalink = x.text}
		entry.each_element("trackback") {|x| trackback = x.text}

		entry.each_element("category") {
			|category| 
			
			hash = category.text.crypt('salt')
			
			if categories_cache[hash] == nil
				id = insertCategory(dbh, category.text)
				categories_cache[hash] = id
			else 
				id = categories_cache[hash]
			end
			
			assignCategory2Post(dbh, postId, id)
		}

		# send info about comments to WordPress database
		commentNr = Integer(0)

		entry.each_element("comment") {

			|comment|
		
			cDate, cNick, cUrl, cBody, cIp = nil
	
			comment.each_element("date") {|x| cDate = x.text}
			comment.each_element("nick") {|x| cNick = x.text}
			comment.each_element("nick_url") {|x| cUrl = x.text}

			comment.each_element("body") {|x| cBody = x.text}
			comment.each_element("ip") {|x| cIp = x.text}

			if cBody != nil
				cBody = dbh.escape_string(cBody)
			else
				cBody = ""
			end

			if cNick != nil
				cNick = dbh.escape_string(cNick)
			else
				cNick = ""
			end

			if cUrl != nil
				cUrl = dbh.escape_string(cUrl)
			else
				cUrl = ""
			end
			
			query = "INSERT INTO " +
				"`" + $table_prefix + "comments` (`comment_post_ID`, `comment_author`, " +
				"`comment_author_url`, `comment_date`, `comment_date_gmt`, " +
				"`comment_content`) VALUES" +
				"('" + postId.to_s + "', '" + cNick + "', '" + cUrl +
				"', '" + date + "', '" + date + "', '" +
				cBody + "');"

			dbh.query(query)

			commentNr = commentNr + 1
	
		}

		# send info about post to WordPress database
		body = dbh.escape_string(body)
		
		# replace GESHi tags
		body = body.gsub(/\{geshi\s+lang="?(\w+)"?\}/, '[sourcecode language="\\1"]').gsub(/\{\/geshi\}/, '[/sourcecode]')
		
		if subject != nil
			subject = dbh.escape_string(subject)
		else
			subject = ""
		end

		if Integer(level_id) > 1
			post_status = "private"
		else
			post_status = "publish"
		end
		
		query = "INSERT INTO " +
			"`" + $table_prefix + "posts` (`post_author`, `ID`, `post_date`, " +
			"`post_date_gmt`, `post_content`, `post_title`, " +
			"`post_status`, `post_modified`, `post_modified_gmt`, " +
			"`guid`, `post_name`, `comment_count`) VALUES" +
			"(1, '" + postId.to_s + "', '" + date + "', '" + date + "', '" + body +
			"', '" + subject + "', '" + post_status + "', '" +
			date + "', '" + date + "', '', '" + permalink + "', '" + commentNr.to_s + "');"

		dbh.query(query)
		
		postId = postId + 1;
		puts postId

	}
	
	# the last thing - update counters for categories
	dbh.query("UPDATE " + $table_prefix + "term_taxonomy SET " + 
		" count = (SELECT COUNT(*) FROM " + $table_prefix + "term_relationships WHERE term_taxonomy_id = " + $table_prefix + "term_taxonomy.term_taxonomy_id) ")

rescue Mysql::Error => e
	puts "Error code: #{e.errno}"
	puts "Error message: #{e.error}"
	puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
ensure
	# disconnect from server
	dbh.close if dbh
end
